package org.vsoc.modules.fortrial.controller;

import java.io.BufferedReader;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executors;
import javax.annotation.PostConstruct;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.aliyun.tea.*;
import com.alibaba.druid.util.StringUtils;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.vsoc.modules.fortrial.entity.ForTrial;
import org.vsoc.modules.fortrial.service.IForTrialService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.system.base.controller.JeecgController;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Value;
import org.jeecg.common.util.RedisUtil;

/**
 * @Description: 申请试用
 * @Author: jeecg-boot
 * @Date: 2025-06-23
 * @Version: V1.0
 */
@Slf4j
@Tag(name = "申请试用")
@RestController
@RequestMapping("/fortrial/forTrial")
public class ForTrialController extends JeecgController<ForTrial, IForTrialService> {
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private IForTrialService forTrialService;

    @Autowired
    private JavaMailSender mailSender;

    /**
     * 分页列表查询
     *
     * @param forTrial
     * @param pageNo
     * @param pageSize
     * @param req
     * @return
     */
    @AutoLog(value = "申请试用-分页列表查询")
    @Operation(summary = "申请试用-分页列表查询")
    @GetMapping(value = "/list")
    public Result<?> queryPageList(ForTrial forTrial,
                                   @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                   @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                   HttpServletRequest req) {
        QueryWrapper<ForTrial> queryWrapper = QueryGenerator.initQueryWrapper(forTrial, req.getParameterMap());
        Page<ForTrial> page = new Page<ForTrial>(pageNo, pageSize);
        IPage<ForTrial> pageList = forTrialService.page(page, queryWrapper);
        return Result.OK(pageList);
    }

    /**
     * 添加
     *
     * @param forTrial
     * @return
     */
    @AutoLog(value = "申请试用-添加")
    @Operation(summary = "申请试用-添加")
    @PostMapping(value = "/add")
    public Result<?> add(@RequestBody ForTrial forTrial) {
        forTrialService.save(forTrial);
        return Result.OK("添加成功！");
    }

    /**
     * 编辑
     *
     * @param forTrial
     * @return
     */
    @AutoLog(value = "申请试用-编辑")
    @Operation(summary = "申请试用-编辑")
    @RequestMapping(value = "/edit", method = {RequestMethod.PUT, RequestMethod.POST})
    public Result<?> edit(@RequestBody ForTrial forTrial) {
        forTrialService.updateById(forTrial);
        return Result.OK("编辑成功!");
    }

    /**
     * 通过id删除
     *
     * @param id
     * @return
     */
    @AutoLog(value = "申请试用-通过id删除")
    @Operation(summary = "申请试用-通过id删除")
    @DeleteMapping(value = "/delete")
    public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
        forTrialService.removeById(id);
        return Result.OK("删除成功!");
    }

    /**
     * 批量删除
     *
     * @param ids
     * @return
     */
    @AutoLog(value = "申请试用-批量删除")
    @Operation(summary = "申请试用-批量删除")
    @DeleteMapping(value = "/deleteBatch")
    public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
        this.forTrialService.removeByIds(Arrays.asList(ids.split(",")));
        return Result.OK("批量删除成功！");
    }

    /**
     * 通过id查询
     *
     * @param id
     * @return
     */
    @AutoLog(value = "申请试用-通过id查询")
    @Operation(summary = "申请试用-通过id查询")
    @GetMapping(value = "/queryById")
    public Result<?> queryById(@RequestParam(name = "id", required = true) String id) {
        ForTrial forTrial = forTrialService.getById(id);
        return Result.OK(forTrial);
    }

    /**
     * 导出excel
     *
     * @param request
     * @param forTrial
     */
    @RequestMapping(value = "/exportXls")
    public ModelAndView exportXls(HttpServletRequest request, ForTrial forTrial) {
        return super.exportXls(request, forTrial, ForTrial.class, "申请试用");
    }

    /**
     * 通过excel导入数据
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
    public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
        return super.importExcel(request, response, ForTrial.class);
    }

    /**
     * 申请试用 - 保存信息
     *
     * @param request
     * @return
     */
    @AutoLog(value = "申请试用-保存")
    @Operation(summary = "申请试用-保存")
    @PostMapping(value = "/storeTrialApplication")
    public Result<?> storeTrialApplication(HttpServletRequest request) {
        try {
            StringBuilder buffer = new StringBuilder();
            BufferedReader reader = request.getReader();
            String line;
            while ((line = reader.readLine()) != null) {
                buffer.append(line);
            }

            // 解析JSON数据
            ObjectMapper mapper = new ObjectMapper();
            Map<String, Object> requestData = mapper.readValue(buffer.toString(), Map.class);


            // 获取参数
            // 获取手机号和验证码
            String phone = (String) requestData.get("phone");
            log.info("手机号: {}", phone);
            if (StringUtils.isEmpty(phone)) {
                phone = (String) requestData.get("tphone");
            }

            // 获取验证码参数
            String verifyCode = (String) requestData.get("validcode");

            // 如果手机号和验证码不为空，则进行验证码验证
            if (!StringUtils.isEmpty(phone) && !StringUtils.isEmpty(verifyCode)) {
                // 从Redis中获取验证码
                String redisKey = "sms:code:" + phone;
                Object storedCode = redisUtil.get(redisKey);

                // 添加ddl过期时间日志
                Long ddl = redisUtil.getExpire(redisKey);
                log.info("验证码剩余ddl: {}秒", ddl);
                if (storedCode != null) {
                    if (ddl != null && ddl <= 0) {
                        storedCode = null;
                        redisUtil.del(redisKey);
                    }
                }

                // 验证码已过期或不存在
                if (storedCode == null) {
                    System.out.println("验证码已过期或不存在，请重新获取验证码");
                    return Result.error("验证码已过期或不存在，请重新获取验证码");
                }

                // 验证码不匹配
                if (!verifyCode.equals(storedCode.toString())) {
                    return Result.error("验证码错误，请重新输入");
                }

                // 验证通过后，删除Redis中的验证码
                redisUtil.del(redisKey);
                log.info("验证码验证成功，已从Redis中删除验证码, 键名: {}", redisKey);
            }

            if (StringUtils.isEmpty(phone)) {
                return Result.error("手机号不能为空");
            }


            // 公司名
            String company = (String) requestData.get("compony");
            // 处理产品选择
            String p1 = (String) requestData.get("1");
            String p2 = (String) requestData.get("2");
            String p3 = (String) requestData.get("3");
            String p4 = (String) requestData.get("4");
            String p5 = (String) requestData.get("5");

            StringBuilder productsSb = new StringBuilder();
            if (!StringUtils.isEmpty(p1)) {
                productsSb.append("1:on;");
            }
            if (!StringUtils.isEmpty(p2)) {
                productsSb.append("2:on;");
            }
            if (!StringUtils.isEmpty(p3)) {
                productsSb.append("3:on;");
            }
            if (!StringUtils.isEmpty(p4)) {
                productsSb.append("4:on;");
            }
            if (!StringUtils.isEmpty(p5)) {
                productsSb.append("5:on;");
            }

            String products = productsSb.toString();
            String gtype = "";

            if (StringUtils.isEmpty(company)) {
                // 兼容官网参数
                company = (String) requestData.get("componey");
                // 来自官网
                String validcode = (String) requestData.get("validcode");
                if (StringUtils.isEmpty(validcode)) {
                    String job = (String) requestData.get("job");
                    if (StringUtils.isEmpty(job)) {
                        gtype = "wp";
                        products = "5:on;";
                        //判断白皮书场景
                        String daywp = (String) requestData.get("0daywp");
                        if ("1".equals(daywp)) {
                            gtype = "0dwp";
                            products = "6:on;";
                            // 0day白皮书下载
                        } else if ("3".equals(daywp)) {
                            gtype = "pdwp";
                            products = "7:on;";
                        } else {
                            String mdps = (String) requestData.get("mdps-en");
                            if (!StringUtils.isEmpty(mdps)) {
                                // 英文白皮书
                                gtype = "mdps-en";
                                products = "8:on;";
                            }
                        }
                    }
                }
//                } else {
//                    // 英文官网，申请手册
//                    String manuals = (String) requestData.get("manuals");
//                    // 英文官网，申请红蓝对抗指南
//                    String guidance = (String) requestData.get("guidance");
//                    if (!StringUtils.isEmpty(manuals)) {
//                        // 英文产品手册
//                        gtype = "manuals";
//                        products = "9:on;";
//                    } else if (!StringUtils.isEmpty(guidance)) {
//                        // 英文红蓝对抗指南
//                        gtype = "guidance";
//                        products = "10:on;";
//                    }
//                }
            }

            if (StringUtils.isEmpty(products)) {
                products = "3:on;";
            }

            // 获取其他基本信息
            String email = (String) requestData.get("email");
            String name = (String) requestData.get("name");
            String firstName = (String) requestData.get("first");
            String lastName = (String) requestData.get("last");
            String country = (String) requestData.get("country");

            // 处理姓名
            if (StringUtils.isEmpty(name)) {
                name = (lastName == null ? "" : lastName) + (firstName == null ? "" : firstName);
            }

            // 获取客户端IP
            String ip = getIpAddress(request);

            // 获取来源URL
            String ref = request.getHeader("Referer");

            // 创建实体对象
            ForTrial forTrial = new ForTrial();
            forTrial.setCompany(company);
            forTrial.setEmail(email);
            forTrial.setName(name);
            forTrial.setFirstName(firstName);
            forTrial.setLastName(lastName);
            forTrial.setPhone(phone);
            forTrial.setProducts(products);
            forTrial.setCountry(country);
            forTrial.setIp(ip);
            forTrial.setGtype(gtype);
            forTrial.setRef(ref);
            forTrial.setCreateTime(new Date());
            forTrial.setUpdateTime(new Date());
            log.info("准备保存用户数据: phone={}, email={}, name={}, company={}, products={}",
                    phone, email, name, company, products);
            // 保存数据
            forTrialService.save(forTrial);

            Result<?> result = sendNotification(forTrial, request);
            if (result.isSuccess()) {
                return Result.OK("申请试用提交成功！");
            } else {
                return Result.error("申请试用提交失败！");
            }
        } catch (Exception e) {
            log.error("申请试用提交失败", e);
            return Result.error("申请试用提交失败：" + e.getMessage());
        }
    }

    /**
     * 发送短信
     *
     * @param phoneNumber 接收短信的手机号码
     */
    @AutoLog(value = "申请试用-发送验证码短信")
    @Operation(summary = "申请试用-发送验证码短信")
    @PostMapping(value = "/sendSms")
    Result<?> sendSms(String phoneNumber) throws Exception {
        //校验1分钟之内只能发一次验证码
        String redisKey1 = "sms:code:" + phoneNumber;
        Object storedCode = redisUtil.get(redisKey1);
        if (ObjectUtils.isNotEmpty(storedCode)) {
            return Result.error("验证码已发送，请稍后再试");
        }
        Client client = createSmsClient();
        // 生成随机四位数字验证码
        String code = generateRandomCode();

        // 在阿里云短信模板中，模板参数名为code
        SendSmsRequest sendSmsRequest = new SendSmsRequest()
                .setPhoneNumbers(phoneNumber)
                .setSignName("安芯网盾")
                .setTemplateCode("SMS_489755188")
                .setTemplateParam("{\"code\":\"" + code + "\"}");
        System.out.println(code);
        System.out.println(client);
        RuntimeOptions runtime = new RuntimeOptions();
        try {
            // 复制代码运行请自行打印 API 的返回值
            SendSmsResponse response = client.sendSmsWithOptions(sendSmsRequest, runtime);
            System.out.println(response.getBody());
            log.info("短信发送结果: {}, 验证码: {}", response.getBody().getCode(), code);
            if ("OK".equals(response.getBody().getCode())) {
                // 短信发送成功，将验证码存入Redis中，过期时间为60秒
                String redisKey = "sms:code:" + phoneNumber;
                redisUtil.set(redisKey, code, 60);
                log.info("验证码已存入Redis，键名: {}, 过期时间: 60秒", redisKey);
            } else {
                log.error("短信发送失败: {}", response.getBody().getMessage());
            }
            return Result.OK("验证码发送成功", phoneNumber);
        } catch (Exception e) {
            log.error("短信发送失败: {}", e);
            return Result.error("验证码发送失败");
        }
    }

    /**
     * 生成随机四位数字验证码
     *
     * @return 四位数字验证码
     */
    private String generateRandomCode() {
        // 生成1000-9999之间的随机数
        int randomNum = 1000 + (int) (Math.random() * 9000);
        return String.valueOf(randomNum);
    }

    /**
     * 创建阿里云连接
     *
     * @return 创建阿里云连接
     */
    private Client createSmsClient() throws Exception {
        Config config = new Config()
                .setAccessKeyId("LTAI5tCb6jiDkeStx37AB1Fd")
                .setAccessKeySecret("kuJhUjaghQD6XbohdbEW35zLnFuO0r")
                .setEndpoint("dysmsapi.aliyuncs.com");
        return new Client(config);
    }

    /**
     * 发送通知
     *
     * @param forTrial 试用申请信息
     */
    private Result<?> sendNotification(ForTrial forTrial, HttpServletRequest request) {
        try {
            // 1. 处理产品名称
            String products = forTrial.getProducts();
            products = products.replace("1:on", "安芯神甲智能内存保护系统");
            products = products.replace("2:on", "系统信息检测工具");
            products = products.replace("3:on", "未知威胁文件检测系统");

            if (StringUtils.isEmpty(forTrial.getCountry())) {
                products = products.replace("4:on", "安芯神鉴终端保护系统");
                products = products.replace("5:on", "应用安全防护系统RASP");
            } else {
                products = products.replace("4:on", "Mobile Device Management");
                products = products.replace("5:on", "Managed Security Service");
            }

            String gtype = forTrial.getGtype();
            if ("mp".equals(gtype)) {
                products = "内存保护系统";
                forTrial.setRef("https://www.anxinsec.com/view/download/");
            } else if ("wp".equals(gtype)) {
                products = "白皮书下载";
                forTrial.setRef("https://www.anxinsec.com/view/download/");
            } else if ("0dwp".equals(gtype)) {
                products = "0day白皮书下载";
                forTrial.setRef("https://www.anxinsec.com/view/download/0day/");
            } else if ("pdwp".equals(gtype)) {
                products = "产品白皮书";
                forTrial.setRef("https://www.anxinsec.com/view/download/product/");
            } else if ("mdps-en".equals(gtype)) {
                products = "英文白皮书";
                forTrial.setRef("https://www.anxinsec.com/en/brochure-download/");
            } else if ("manuals".equals(gtype)) {
                products = "Company Product Manuals";
                forTrial.setRef("https://www.anxinsec.com/en/");
            } else if ("guidance".equals(gtype)) {
                products = "A Guidance for Defense Team";
                forTrial.setRef("https://www.anxinsec.com/en/");
            }

            // 2. 组装通知消息
            String message = "新来一条试用申请：\n" +
                    "邮箱：" + forTrial.getEmail() + "\n" +
                    "姓名：" + forTrial.getName() + "\n" +
                    "电话：" + forTrial.getPhone() + "\n" +
                    "公司：" + forTrial.getCompany() + "\n" +
                    "申请模块：" + products + "\n" +
                    "申请时间：" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(forTrial.getCreateTime()) + "\n" +
                    "客户端IP：" + getIpAddress(request) + "\n" +
                    "客户端URL：" + forTrial.getRef();

            // 4. 发送邮件通知 (实际实现需调用邮件服务)
            sendEmail("zentao@anxinsec.com", "datamar@anxinsec.com", "新来一条试用申请", message);
//            sendEmail("zentao@anxinsec.com", "2581015880@qq.com", "新来一条试用申请", message);
            log.info("邮件通知已发送至管理员");
            return Result.OK("发送邮件成功！");
        } catch (Exception e) {
            log.error("发送邮件通知失败", e);
            return Result.error("发送邮件通知失败：" + e.getMessage());
        }
    }

    /**
     * 发送邮件
     *
     * @param to      收件人邮箱
     * @param subject 邮件主题
     * @param content 邮件内容
     */
    private void sendEmail(String from, String to, String subject, String content) throws MessagingException {
        try {

            JavaMailSenderImpl senderImpl = (JavaMailSenderImpl) mailSender;
            senderImpl.setHost("smtp.exmail.qq.com");
            senderImpl.setPort(465);
            senderImpl.setUsername("linxer@anxinsec.com");
            senderImpl.setPassword("Anxinwangdun@2020");

            Properties props = senderImpl.getJavaMailProperties();
            props.put("mail.smtp.auth", "true");
            props.put("mail.smtp.ssl.enable", "true");
            props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
            props.put("mail.smtp.timeout", "10000");
            props.put("mail.debug", "true");

            MimeMessage message = mailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");

            helper.setFrom("linxer@anxinsec.com", "anxin@email.com");
            helper.setTo(to);
            helper.setSubject(subject);
            // true表示支持HTML格式
            helper.setText(content, false);

            mailSender.send(message);
            log.info("发送邮件到 {}, 主题: {}, 内容: {}", to, subject, content);

        } catch (Exception e) {
            log.error("邮件发送失败", e);
            throw new RuntimeException("邮件发送失败: " + e.getMessage());
        }
    }

    /**
     * 获取客户端IP地址
     *
     * @param request 请求对象
     * @return IP地址
     */
    private String getIpAddress(HttpServletRequest request) {
        String[] headers = {"x-forwarded-for", "Proxy-Client-IP", "WL-Proxy-Client-IP"};
        String ip = null;

        for (String header : headers) {
            ip = request.getHeader(header);
            if (isValidIp(ip)) {
                break;
            }
        }

        return isValidIp(ip) ? ip : request.getRemoteAddr();
    }

    private boolean isValidIp(String ip) {
        return ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip);
    }

}
